import subprocess
import threading
import queue
import time
import sys

def run_command(command, print_output=True):
    """
    执行命令并实时捕获stdout和stderr，使用独立队列分离输出
    :param command: 要执行的命令（列表形式）
    :param print_output: 是否实时打印输出
    :return: 元组 (stdout内容, stderr内容)
    """
    # 启动子进程
    process = subprocess.Popen(
        command,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        bufsize=1,  # 行缓冲
        text=True,  # 返回字符串而非字节
        errors='replace'  # 替换解码错误字符
    )

    # 为stdout和stderr创建独立队列
    stdout_queue = queue.Queue()
    stderr_queue = queue.Queue()
    stdout_lines = []
    stderr_lines = []

    def stdout_reader():
        """从stdout读取数据并放入专用队列"""
        try:
            for line in process.stdout:
                stdout_queue.put(line)
                stdout_lines.append(line)
        finally:
            stdout_queue.put(None)  # 发送结束信号
            process.stdout.close()

    def stderr_reader():
        """从stderr读取数据并放入专用队列"""
        try:
            for line in process.stderr:
                stderr_queue.put(line)
                stderr_lines.append(line)
        finally:
            stderr_queue.put(None)  # 发送结束信号
            process.stderr.close()

    # 启动读取线程
    stdout_thread = threading.Thread(target=stdout_reader, daemon=True)
    stderr_thread = threading.Thread(target=stderr_reader, daemon=True)
    
    stdout_thread.start()
    stderr_thread.start()

    # 处理队列中的输出
    stdout_active = True
    stderr_active = True
    
    while stdout_active or stderr_active:
        # 检查stdout队列
        if stdout_active:
            try:
                line = stdout_queue.get_nowait()
                if line is None:
                    stdout_active = False
                elif print_output:
                    print(f"[stdout] {line.rstrip()}")
            except queue.Empty:
                pass
        
        # 检查stderr队列
        if stderr_active:
            try:
                line = stderr_queue.get_nowait()
                if line is None:
                    stderr_active = False
                elif print_output:
                    print(f"[stderr] {line.rstrip()}", file=sys.stderr)
            except queue.Empty:
                pass
        
        # 避免忙等待
        time.sleep(0.01)  # 10ms延迟减少CPU使用
    
    # 等待进程结束
    process.wait()
    
    # 返回捕获的输出
    return ''.join(stdout_lines), ''.join(stderr_lines)

# 测试示例
if __name__ == "__main__":
    # 测试命令（同时输出stdout和stderr）
    test_cmd = [
        "python",
        "-c",
        """
import sys, time
print('stdout start')
for i in range(5):
    print(f'stdout {i}')
    print(f'stderr {i}', file=sys.stderr)
    time.sleep(0.5)
print('stdout end')
"""
    ]
    
    print("执行命令并实时捕获输出:")
    stdout, stderr = run_command(test_cmd)
    
    print("\n捕获结果:")
    print("=== stdout ===")
    print(stdout)
    print("=== stderr ===")
    print(stderr)
